package com.lancoo.znbkxx.teacher.aibkTestCoach.auidoPlayer;

import android.graphics.drawable.AnimationDrawable;
import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaMetadataRetriever;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;

import com.lancoo.znbkxx.teacher.R;
import com.lancoo.znbkxx.teacher.aibkTestCoach.aibkTools.MyToast;
import com.lancoo.znbkxx.teacher.utils.FileUtils;
import com.lancoo.znbkxx.teacher.utils.ToastUtils;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author Richie on 2018.10.26
 */
public class AudioTracker implements DefaultLifecycleObserver {
    private static final String TAG = "AudioTracker";

    private final static int SAMPLE_RATE = 16000;
    // 单声道，所有设备都支持
    private final static int CHANNEL = AudioFormat.CHANNEL_OUT_MONO;
    // 位深 16 位，所有设备都支持
    private final static int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
    // 缓冲区字节大小
    private int mBufferSizeInBytes = 0;
    // 播放对象
    private AudioTrack mAudioTrack;
    // 文件名
    private String mFilePath = "";
    // 状态
    private volatile Status mStatus = Status.STATUS_NO_READY;
    // 单任务线程池
    private AnimationDrawable animationDrawable;

    private ImageView mIvAudioAnim;

    private ExecutorService mExecutorService = Executors.newSingleThreadExecutor();

    private Handler mMainHandler = new Handler(Looper.getMainLooper());

    private PlayListener mPlayListener;

    String mAudioPath;

    public void createAudioTrack() throws IllegalStateException {
        mBufferSizeInBytes = AudioTrack.getMinBufferSize(SAMPLE_RATE, CHANNEL, AUDIO_FORMAT);
        if (mBufferSizeInBytes <= 0) {
            throw new IllegalStateException("AudioTrack is not available " + mBufferSizeInBytes);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mAudioTrack = new AudioTrack.Builder()
                    .setAudioAttributes(new AudioAttributes.Builder()
                            .setUsage(AudioAttributes.USAGE_MEDIA)
                            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                            .setLegacyStreamType(AudioManager.STREAM_MUSIC)
                            .build())
                    .setAudioFormat(new AudioFormat.Builder()
                            .setEncoding(AUDIO_FORMAT)
                            .setSampleRate(SAMPLE_RATE)
                            .setChannelMask(CHANNEL)
                            .build())
                    .setTransferMode(AudioTrack.MODE_STREAM)
                    .setBufferSizeInBytes(mBufferSizeInBytes)
                    .build();
        } else {
            mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE, CHANNEL, AUDIO_FORMAT,
                    mBufferSizeInBytes, AudioTrack.MODE_STATIC);
        }
        mStatus = Status.STATUS_READY;
    }

    public void setMFilePath(String filePath) {
        mFilePath = filePath;
    }

    public String getmFilePath() {
        return mFilePath;
    }

    public void setImageView(ImageView imageView) {
        mIvAudioAnim = imageView;
        mIvAudioAnim.clearAnimation();
        mIvAudioAnim.setImageResource(R.drawable.anim_laba);
        animationDrawable = (AnimationDrawable) mIvAudioAnim.getDrawable(); // 1. 获取动画对象
    }

    public int getDuration() {
        int duration;
        try {
            MediaMetadataRetriever mmr = new MediaMetadataRetriever();
            mmr.setDataSource(mFilePath);
            double mill = Double.parseDouble(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
            BigDecimal decimal = new BigDecimal(mill / 1000).setScale(0, BigDecimal.ROUND_HALF_UP);
            duration = decimal.intValue();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
        return duration;
    }

    /**
     * 开始播放
     */
    public void start() throws IllegalStateException {
        if (mStatus == Status.STATUS_NO_READY || mAudioTrack == null || mAudioTrack.getState() == AudioTrack.STATE_UNINITIALIZED) {
            throw new IllegalStateException("播放器尚未初始化");
        }
        if (mStatus == Status.STATUS_START) {
            stop();
        }
        if (!mFilePath.isEmpty()) {
            mStatus = Status.STATUS_START;
        } else {
            MyToast.INSTANCE.showToast("音频下载中，请稍等");
        }
        mExecutorService.execute(() -> {
            try {
                playAudioData();
            } catch (IOException e) {
                mMainHandler.post(() -> {
                });
            }
        });
    }

    private void playAudioData() throws IOException {
        InputStream dis = null;
        if (!mFilePath.isEmpty()) {
            dis = new DataInputStream(new BufferedInputStream(new FileInputStream(mFilePath)));
        } else {
            if (mPlayListener != null) {
                mPlayListener.playPrepare();
            }
            return;
        }
        try {
            if (mPlayListener != null) {
                mPlayListener.playStart();
            }
            mMainHandler.post(this::startAnim);
            byte[] bytes = new byte[mBufferSizeInBytes];
            int length;
            mAudioTrack.play();
            // write 是阻塞的方法
            while ((length = dis.read(bytes)) != -1 && mStatus == Status.STATUS_START) {
                mAudioTrack.write(bytes, 0, length);
            }
            mMainHandler.post(() -> {
                stopAnim();
                mStatus = Status.STATUS_FINISH;
            });
            if (mPlayListener != null) {
                mPlayListener.playFinish();
            }

        } finally {
            if (dis != null) {
                dis.close();
            }
        }
    }

    public void stop() throws IllegalStateException {
        if (mStatus == Status.STATUS_NO_READY || mStatus == Status.STATUS_READY) {
        } else {
            mStatus = Status.STATUS_STOP;
            if (mAudioTrack != null) {
                stopAnim();
            }
            if (mPlayListener != null) {
                mPlayListener.playFinish();
            }
            mAudioTrack.pause();
            mAudioTrack.flush();
            mAudioTrack = null;
            createAudioTrack();
        }
    }

    public void release() {
        mStatus = Status.STATUS_NO_READY;
        if (mAudioTrack != null) {
            mAudioTrack.release();
            mAudioTrack = null;
        }
    }

    public void pause() {
        if (mStatus == Status.STATUS_START) {
            mAudioTrack.pause();
        }
    }

    /**
     * 播放对象的状态
     */
    public enum Status {
        //未开始
        STATUS_NO_READY,
        //预备
        STATUS_READY,
        //播放
        STATUS_START,
        //播放结束
        STATUS_FINISH,
        //停止
        STATUS_STOP
    }

    private void startAnim() {
        if (mIvAudioAnim != null) {
            mIvAudioAnim.setImageResource(R.drawable.anim_laba);
            animationDrawable = (AnimationDrawable) mIvAudioAnim.getDrawable(); // 1. 获取动画对象
            animationDrawable.start();
        }
    }

    public void stopAnim() {
        if (mIvAudioAnim != null) {
            animationDrawable.stop();
            animationDrawable.selectDrawable(0);
            mIvAudioAnim.clearAnimation();
        }
    }

    /**
     * 下载音频
     *
     * @param path     下载文件的地址
     * @param fileName 文件名字
     */
    public void downLoadAudio(final String path, final String fileName) {
        new Thread(() -> {
            try {
                URL url = new URL(path);
                HttpURLConnection con = (HttpURLConnection) url.openConnection();
                con.setReadTimeout(5000);
                con.setConnectTimeout(5000);
                con.setRequestProperty("Charset", "UTF-8");
                con.setRequestMethod("GET");
                if (con.getResponseCode() == 200) {
                    InputStream is = con.getInputStream();//获取输入流
                    FileOutputStream fileOutputStream = null;//文件输出流
                    if (is != null) {
                        FileUtils fileUtils = new FileUtils(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.lancoo.znbkxx.teacher/" + "files/audio/");
                        fileOutputStream = new FileOutputStream(
                                fileUtils.createFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.lancoo.znbkxx.teacher/" + "files/audio/", fileName));//指定文件保存路径，代码看下一步
                        //记录本地保存路径
                        mAudioPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.lancoo.znbkxx.teacher/" + "files/audio/" + fileName;
                        byte[] buf = new byte[1024];
                        int ch;
                        while ((ch = is.read(buf)) != -1) {
                            fileOutputStream.write(buf, 0, ch);//将获取到的流写入文件中
                        }
                    }
                    if (fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                    if (!mAudioPath.isEmpty()) {
                        setMFilePath(mAudioPath);
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

    public void deleteAudio() {
        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.lancoo.znbkxx.teacher/" + "files/audio/";
        File audios = new File(path);
        if (audios.exists()) {
            deleteFile(path);
        }
    }

    private void deleteFile(String filePath) {
        try {
            File file = new File(filePath);//获取SD卡指定路径
            File[] files = file.listFiles();//获取SD卡指定路径下的文件或者文件夹
            for (File value : files) {
                if (value.isFile()) {//如果是文件直接删除
                    File photoFile = new File(value.getPath());
                    photoFile.delete();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public interface DownListener {
        void downStart();

        void downFinish(String path);
    }

    public void setPlayListener(PlayListener listener) {
        mPlayListener = listener;
    }

    public interface PlayListener {
        void playPrepare();

        void playStart();

        void playFinish();
    }

    @Override
    public void onDestroy(@NonNull LifecycleOwner owner) {
        deleteAudio();
    }

    @Override
    public void onResume(@NonNull LifecycleOwner owner) {
        pause();
    }

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        pause();
    }

    @Override
    public void onPause(@NonNull LifecycleOwner owner) {
        pause();
    }
}